<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of Abstract
 *
 * @author Ernet
 */
abstract class DatabaseAbstract extends DatabaseQuery{
      
    
    /**
     * obj class 
     * @var App_Class_Abstract
     */
     protected $_class;
    /**
     * collection obj class
     * @var App_Class_Collection_Abstract
     */
     protected $_collection;
    
    /**
     * set up the database
     * @param array $config 
     */
    public function __construct($config = array()) {
        
    }
    
    
    /**
     * get all rows in objs
     * @return App_Class_Collection_Abstract 
     */
    public function getAll(){
	
	//pobrac z default dal funkcje
	
	
	///////////////////////////////////////////////////////////////////////////////
	$db = Registry::Get($this->getDatabaseType());
	
	$joinString = null;
	$selectString = null;

	
	if (is_array($this->getJoin())) {
		foreach ($this->getJoin() as $type => $arrayJoin) {
		    foreach($arrayJoin as $key => $value)
		    {
			$dalClassName = 'Dal' . $key;
			$dalClass = new $dalClassName();
			
			list($key, $alias) = array_merge(explode(' ', $dalClass->get_class()), array(null)); //aliasy w joinach
			if (trim($this->toSelect($dalClass->get_class(),$dalClass->get_name(), $this->getQueryFields(), $alias)) != "") //aliasy w joinach
			{
			    $selectString .="," . $this->toSelect($dalClass->get_class(),$dalClass->get_name(), $this->getQueryFields(), $alias); //aliasy w joinach
			}
			$joinString .= $type . ' JOIN ' . $dalClass->get_name() . ' ON ' . $this->_name . '.id_' . $dalClass->get_name() . '=' . $dalClass->get_name() . '.id_' . $dalClass->get_name();
		    }
		}
	}
	
	if ($this->getCount() == true )
	{
	    $select = "count($this->_primary) as count";
	}
	else if($this->getAsCount())
	{
	    $select = $this->getAsCount();
	}
	else
	{
	    $select = " " . $this->toSelect($this->_class,$this->_name, $this->getQueryFields()) . " " . $selectString . " " . $this->getSelectFieldsQuery();
	}


	if ($this->getOperationType() != 'SELECT')
		$select = null;


	$updatePart = null;

	if ($this->getOperationType() != 'UPDATE') {
		$queryPart2 = " FROM ";
	} else {
		$queryPart2 = null;
		$updateQuery = array();


		foreach ($dalObj->getUpdateFileldArray() as $key => $value) {
			$updateQuery[] = $key . "='" . $db->Escape($value) . "'";
		}
		$updatePart = " SET " . implode(',', $updateQuery);
	}


	$sql = $this->getOperationType() . " " . $select . $queryPart2 . $this->_name . " " . $updatePart . $joinString . " WHERE 1=1 ";

	
	foreach ($this->getCondition() as $key => $valueArray) {
	    
		if(!is_array($valueArray))
			$valueArray = array($valueArray);

		foreach ($valueArray as $value) {
			if (is_array($value)) {
				if (!isset($value['split']))
					$value['split'] = ' AND ';

				$sql .= ( is_numeric($value['value']) || $value ? " " . $value['split'] . " " . $key . " " . $value['condition'] . " " . $value['value'] : "");
			}
			else
				$sql .= ( is_numeric($value) || $value ? " AND " . $key . " = '" . $value . "'" : "");
		}
	}
	$sql .=
			( trim($this->getGroupBy()) ? " GROUP BY " . $this->getGroupBy() : "") .
			( (trim($this->getHaving()) && $this->getCount() == false) ? " HAVING " . $this->getHaving() : "") .
			( trim($this->getSortBy()) ? " ORDER BY " . $this->getSortBy() : "") .
			( $this->getLimit() ? " LIMIT " . $this->getLimit() : "") .
			" ";
	
	try {
	    $stmt = $db->prepare($sql);

	    if ($this->getCacheTime() > 0) {
		$stmt->CacheStart($this->getCacheTime());
	    }
	} catch (MysqlException $e) {
	    
	}
	$stmt->execute();	
	$array = $stmt->fetchAllAssoc();
	$collection = new $this->_collection;
	$className = $this->_class;

	for ($i = 0; $i < count($array); $i++) 
	{
	    $obj = new $className();
	    $obj->FromArray($array[$i], 1);
	    if (is_array($this->getJoin()))
	    {
		foreach ($this->getJoin() as $type => $arrayJoin) 
		{
		    foreach($arrayJoin as $key => $valueObjName)
		    {
			$valueObj = new $key();
			list($key, $alias) = array_merge(explode(' ', $key), array(null)); //aliasy w joinach
			$valueObj->FromArray($array[$i], 1); //aliasy w joinach
			$func = "set" . $key;
			$obj->$func($valueObj);
		    }
		}
	    }
	    $collection->put($obj,$obj->getId());
	}
	return $collection;
    }
    
    public function listFromSqlToCollection($sql,$params=array(),$insertById=true){
        $queryData = $this->loadCacheQuery($sql, $params);

        if ($queryData==false){
            $rows = $this->getAdapter()->fetchAll( $sql );            
            
            $collection = new $this->_collection();
            foreach ($rows AS $row){
                $obj = $this->__toObj($row);       
                if ($insertById)
                    $collection->put($obj,$obj->getId());
                else
                    $collection->put($obj);
            }
            $this->saveCacheQuery($sql, $params,$collection);
            return $collection;
        }else{
            return $queryData;
        }
    }
    
    /**
     * get one row by own id
     * @param int $id
     * @return _obj
     */
    public function getById($id){                
        $where = $this->getAdapter()->quoteInto($this->_primary.' = ?', $id);
        $sql = $this->select()->where($where);

        $params = func_get_args();
        return $this->getObj($sql,$params);
    }
    
    public function getObj($sql,$params=array()){
        $queryData = $this->loadCacheQuery($sql, $params);

        if ($queryData==false){
            $row = $this->getAdapter()->fetchRow( $sql );
            $this->saveCacheQuery($sql, $params,$row);
            if ($row==null) 
                return null;
            else   
                return $this->__toObj ($row);            
        }else{
            return $this->__toObj ($queryData);
        }        
    }
    
    /**
     *
     * @param string $sql
     * @param array $params 
     */
    protected function loadCacheQuery($sql,$params){
//        $isDBCashed = Zend_Registry::get('config')->cache->databaseAbstract;
//        $cache = Zend_Registry::get('cache');
//        $cacheName = $this->getCacheName($sql,$params);              
//        if( ($data = $cache->load($cacheName)) !== false && $isDBCashed) {        
//            return $data;
//        }else{
//            return false;
//        }
    }
    /**
     *
     * @param string $sql
     * @param array $params 
     * @param obj $obj
     */
    protected function saveCacheQuery($sql,$params,$obj){
//        $isDBCashed = Zend_Registry::get('config')->cache->databaseAbstract;
//        $cache = Zend_Registry::get('cache');
//        $cacheName = $this->getCacheName($sql,$params);        
//        if( $isDBCashed) {        
//            $cache->save($obj,$cacheName);
//        }
    }
    
    protected function getCacheName($sql,$params){
//        return 'databaseAbstract_'.md5($sql.'__'.print_r($params,true));
    }
    
    
    /**
     * save obj to database
     * @param App_Class_Abstract $obj 
     */
    public function save($obj){
        if (intval($obj->getId())>0){
            $primary = $this->_primary;
            if (is_array($this->_primary)) $primary = current($this->_primary);
            $where = $this->getAdapter()->quoteInto($primary.' = ?', $obj->getId());
            $this->update($obj->__toSqlArray(), $where);
            
            return $obj->getId();
        }else{
            $this->insert($obj->__toSqlArray());
            return $this->getAdapter()->lastInsertId();            
        }
    }        
    
    /**
     * remove by id
     * @param int id
     */
    public function removeById($id){
        $primary = $this->_primary;
        if (is_array($this->_primary)) $primary = current($this->_primary);
        $where = $this->getAdapter()->quoteInto($primary.' = ?', $id);
        $this->delete($where);
    }     
    
    /**
     * remove by id
     * @param int id
     */
    public function removeByGroup($id){
        $where = $this->getAdapter()->quoteInto('`group` = ?', $id);
        $this->delete($where);
    }    
    
    
    /**
     * convert array to own obj 
     * @param array $array
     * @return _class 
     */
    public function __toObj($array){
        $obj = new $this->_class();
        $obj->__fromArray($array);
        return $obj;
    }
    
}
